package com.cx.common.util;

import com.cx.common.cons.CharacterCons;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @author flysand
 * @package com.cx.common.util
 * @date 2021-11-08 22:27
 * @des Md5Utils:
 */
public class Md5Utils {

    private final static String MD5 = "MD5";

    public static MessageDigest getMd5Digest() {
        try {
            return MessageDigest.getInstance(MD5);
        } catch (NoSuchAlgorithmException var2) {
            throw new IllegalArgumentException(var2);
        }
    }


    public static byte[] md5(byte[] data) {
        return getMd5Digest().digest(data);
    }

    /**
     * md5字符串
     *
     * @param data 加密字符串
     * @return md5后的字符串
     */
    public static String md5(String data) {
        byte[] bytes = md5(StringUtils.getBytesUtf8(data));

        StringBuilder builder = new StringBuilder();
        for (byte b : bytes) {
            int bt = b & 0xff;
            if (bt < 16) {
                builder.append(0);
            }
            builder.append(Integer.toHexString(bt));
        }
        return builder.toString();
    }

    /**
     * md5 + salt
     *
     * @param data     加密字符串
     * @param salt     盐值
     * @param saltMode 加盐类型
     * @return 加盐后的md5值
     */
    public static String md5Salt(String data, String salt, SaltMode saltMode) {
        if (StringUtils.isEmpty(salt)) {
            return md5(data);
        }
        switch (saltMode) {
            case PRE:
                return md5(salt + data);
            case SUFFIX:
                return md5(data + salt);
            case PRE_REPEAT:
                return md5(salt + md5(data));
            case SUFFIX_REPEAT:
            default:
                return md5(md5(data) + salt);
        }
    }

    /**
     * md5字符串 - 转大写
     *
     * @param data 加密字符串
     * @return md5后的字符串
     */
    public static String md5Uppercase(String data) {
        return md5(data).toUpperCase();
    }

    /**
     * md5 + salt转大写
     *
     * @param data     加密字符串
     * @param salt     盐值
     * @param saltMode 加盐类型
     * @return 加盐后的md5值
     */
    public static String md5SaltUpperCase(String data, String salt, SaltMode saltMode) {
        return md5Salt(data, salt, saltMode).toUpperCase();
    }


    /**
     * 获取salt
     *
     * @param source     salt源字符串
     * @param saltSource 获取salt的方式类型  从UUID还是其他
     * @return salt
     */
    public static String getSalt(String source, SaltSource saltSource) {
        String salt = source;
        switch (saltSource) {
            // 可能的其他参数
            case OTHER:
                break;
            // 默认从UUID取
            case UUID:
            default:
                // 取userId（UUID）第一位、最后一位、第一个-的前后两位，最后一个-的前后两位
                int firstIndex = source.indexOf(CharacterCons.HYPHEN);
                int lastIndex = source.lastIndexOf(CharacterCons.HYPHEN);

                salt = String.valueOf(source.charAt(0)) + source.charAt(source.length() - 1) +
                        source.charAt(firstIndex - 1) + source.charAt(firstIndex + 1) +
                        source.charAt(lastIndex - 1) + source.charAt(lastIndex + 1);

        }
        return salt;
    }


    /**
     * 加盐方式
     */
    public enum SaltMode {
        PRE,
        SUFFIX,
        PRE_REPEAT,
        SUFFIX_REPEAT

    }

    /**
     * 以什么方式获取salt
     */
    public enum SaltSource {
        UUID,
        OTHER;
    }

    public static void main(String[] args) {
        String data = "123456";
        System.out.println(md5(data));
        System.out.println(md5Salt(data, "abc", SaltMode.PRE));
//        System.out.println(DigestUtils.md5Hex(data));
    }

}
